package yf.mall.utils;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.cglib.core.Converter;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * description: 对象转换器
 *
 * @author Careerly
 * @version V1.0
 * @date 2018/8/29 下午4:26
 */
public class CustomBeanCopier {

    /**
     * description: 对象属性copy
     *
     * @param src src
     * @return rClass
     * @author Careerly
     * @date 2018/8/29 下午4:53
     **/
    public static <I, R> R copy(I src, Class<R> rClass) {
        if(src == null){
            return null;
        }
        R target = null;
        try {
            target = rClass.newInstance();
            CachedBeanCopier.copy(src, target);
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }

        return target;
    }

    /**
     * description: 对象属性copy
     *
     * @param src src
     * @param target target
     * @author Careerly
     * @date 2018/8/29 下午4:53
     **/
    public static <I, R> R copy(I src, R target) {
        CachedBeanCopier.copy(src, target);
        return target;
    }

    /**
     * description: 对象属性copy
     *
     * @param src src
     * @param target target
     * @author Careerly
     * @date 2018/8/29 下午4:53
     **/
    public static <I, R> R copy(I src, R target, Converter converter) {
        CachedBeanCopier.copy(src, target, converter);
        return target;
    }

    /**
     * description: 对象属性copy
     *
     * @param src src
     * @return rClass
     * @author Careerly
     * @date 2018/8/29 下午4:53
     **/
    public static <I, R> R copy(I src, Class<R> rClass, Converter converter) {
        R target = null;
        try {
            target = rClass.newInstance();
            CachedBeanCopier.copy(src, target, converter);
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }

        return target;
    }

    /**
     * 将source的所有对象copy到desc中
     *
     * @param source 原对象列表
     * @param desc 目标对象列表
     * @param descClazz 目标对象类型
     */
    public static void copyListProperties(List source, List desc, Class descClazz) {
        for (Object o : source) {
            try {
                Object d = descClazz.newInstance();
                copy(o, d);
                desc.add(d);
            } catch (InstantiationException | IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * 获取到对象中属性为null的属性名
     * 
     * @param source
     * @return 要拷贝的对象
     */
    private static String[] getNotNullPropertyNames(Object source) {
        final BeanWrapper src = new BeanWrapperImpl(source);
        // 获取包装对象的PropertyDescriptors
        java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors();

        Set<String> emptyNames = new HashSet<>();
        for (java.beans.PropertyDescriptor pd : pds) {
            // 获取属性值为空的属性名
            Object srcValue = src.getPropertyValue(pd.getName());
            if (srcValue != null){
                emptyNames.add(pd.getName());
            }
        }
        String[] result = new String[emptyNames.size()];
        return emptyNames.toArray(result);
    }

    /**
     * 仅设置target中的空值
     * 
     * @param source 原对象
     * @param target 目标对象
     */
    public static void copyPropertiesIgnoreNotNull(Object source, Object target) {
        BeanUtils.copyProperties(source, target, getNotNullPropertyNames(target));
    }
}
